Micron Document
Gemini Proxy


bbs.geminispace.org bbs.geminispace.org/s/C_Programming/46759
If i have a functon like "int function1(...) {}", how to make this function receive an array like "char NOMES_VAR_INT[MAXIMO_VARIAVEIS][10] = {};" as an input?

Aug 07 · 3 days ago


14 Comments ↓

it really depends on your situation. however, as i understand, you want the array to be the function's parameter?

to do that, you can make the function signature be something like this:

int function1(char**arg)
because arrays unfold into pointers in c, a type like
SomeType[]
is the exact same as
SomeType*
hope this helps! :)


What gradma says pretty much covers it, but to add:

You can also define the function with an array type, with a few caveats:
int func(char arr[10]);
The caveats are that anything you do inside of 'func' will implicitly treat arr like a char**, so e.g. doing sizeof(arr) will give you 8 on an amd64 system instead of 10 like you'd expect (8 is the same as sizeof(char**)).

You will also get a compiler warning if you pass anything to func() that isnt length 10.

I would take gradma's approach and also add a length parameter so you know how long your array is explicitly:
int func(char** arr, unsigned int arrlen);


@gh0stb0ners first of all, it's grad or grad man, lol ;p

and secondly, if the length is guaranteed to be fixed (as it appears here) there is little to no need for a length parameter


Now for some bad advice from a Forth/Lisp coder who finds that the C type system is just in the way most of the time, especially when writing complicated compilers and such and things with a lot of assembly code

When I find that I spend way too much time satisfying the C compiler with types, constness and such nonsense I just pass things around as a void pointer or an unsigned int, and deal with them as I see fit.

I call it C--.

Your mileage may vary but works for me in _some_ kinds of crap I have to deal with.

But it pays to understand how to do things correctly.

Think of it this way. I've been using table saws my whole life, and the first thing I do is remove the stupid safety guard that is just in my way and makes things slower and more dangerous -- for me. I still have all my digits and take risks very seriously. But in the end a tool is there to help you get things done. How you use it is up to you.


@stack as someone who made a living off C and ASM for 15 years, I do have to say there is a MASSIVE difference between "good" C and what most people write.


While I wouldn't go quite as far as @stack, I think a case can be made for flattening multi-dimensional arrays into single-dimenstional arrays in C. The language dosen't express mutli-dimentional arrays very elegantly, and code that uses them can be hard to read and to maintain. Just my $0.02, of course.


This is a cool discussion because no matter what you do, something will be terrible, lol.

AFAIK (correct me, pls) the point of declaring a 2D array in C is only one: C handles pointer arithmetic for you for the cost of very specific types. So if you don't mind @stack's C-- (loved the term), you could have:

int function1(void *arr, rows, cols) {
char (* local_arr)[cols] = (char (*)[cols]) arr;
// use local_arr[i][j] normally
// ?
// profit
}

which is the most horrible syntax since LISP but lets you use local_arr[i[j] without risking function1 pointing somewhere else leaking memory (as a char** would).


@gradmna 's claim that an array of array of chars will be compatible with a pointer-to-pointer-to-char, is incorrect.

void func(char **arg) {
return;
}

>define MAXIMO_VARIAVEIS 256
int main(void) {
char NOMES_VAR_INT[MAXIMO_VARIAVEIS][10] = {};
func(NOMES_VAR_INT);
return 0;
}
----
$ gcc bad-func.c
bad-func.c: In function ‘main’:
bad-func.c:8:10: error: passing argument 1 of ‘func’ from incompatible pointer
type [-Wincompatible-pointer-types]
8 | func(NOMES_VAR_INT);
| ^~~~~~~~~~~~~
| |
| char (*)[10]
bad-func.c:1:18: note: expected ‘char **’ but argument is of type ‘char (*)[10
1 | void func(char **arg) {
| ~~~~~~~^~~
And there is no straightforward way to convert between them, either.

Only the outermost layer of "array" in a type converts directly to "pointer" instead. This makes sense if you think about it, bcc an array of pointers does not have at all the same representation as an array of arrays. (By "outermost" I mean in the English description of the type: array of X arrays of 10 char, the X gets turned to pointer. Usually, the innermost in the C type declaration: C type declarations are read inside-to-out, postfixes before prefixes (as modified by parentheses))

As others mentioned, though, flattening may be your best bet. You could certainly just pass an argument of type char[MAXIMO_VARIAVEIS][10] (which, as the compiler suggests, is really a char(*)[10], or pointer to an array of 10 char. But, probably better to pass a pointer to the first character, if the function knows the array dimensions (which, in any case, it must).

So:

void func(char *arg) {
...
}

int main(void) {
...
func(&NOMES_VAR_INT[0][0]);
...
}
(you could also equivalently pass NOMES_VAR_INT[0] instead of NOMES_VAR_INT[0][0], as they mean the same thing after array-to-pointer conversion... but I find the latter considerably more understandable.)

There is a tool on Unix called 'cdecl', for converting between English and C type notation. I recommend getting that and playing around with it a bit to understand more about C types. (Probably also obtainable in some manner for Windows—I'm guessing it's just ANSI C, or close to it.)

Further reading, from the comp.lang.c faq (I'm sure it's available by gemini somewhere, definitely gopher, but https links is what I have handy):
https://c-faq.com/decl/cdecl1.html
https://c-faq.com/aryptr/index.html


@shizukado ive never had that happen? is this some special edge case in c where this happens? i swear i've done an implicit cast from an array to a pointer, but maybe multi dimensional arrays behave differently?


@gradmna oops...sorry about that, I promise I can mostly read.


C pointers and arrays do have su tle differences.


@gradmna exactly. *One* array becomes one pointer (under many, but not all, situations); but multi-arrays do not become multi-pointers. An array expression becomes a pointer to its first element. If its first element is an array, then it will be a pointer to an array.


@gh0stb0ners no no, its okay, im just saying that for next time :)


>include <stdio.h>
>include <stdint.h>

typedef char type; // example

void coolFunc(type**thing, size_t xLen, size_t yLen) {
size_t x;
size_t y = 0;
while (y<yLen) {
x=0;
while (x<xLen) {
printf("x=%zu, y=%zu, value=%d", x, y, thing[y][x]);
x++;
}
y++;
}
}

int main() {
type test[][3] = {
{1,2,3},
{2,3,4},
{11,2,0xa9}
};
coolFunc((type**)test, 3, 3);
return 0;
}
apparently that cause a segfault. eh, i probably messed something up. regardless, didn't really work. maybe you guys are right, lol


you're on bbs.geminispace.org/s/C_Programming/46759